home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 631 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  4.1 KB

  1. Path: news.th-darmstadt.de!news
  2. From: Enno Sandner <enno@intellektik.informatik.th-darmstadt.de>
  3. Newsgroups: comp.lang.c++,comp.sys.mac.programmer.codewarrior,comp.sys.mac.oop
  4. Subject: Re: Help needed with Runtime Type Info
  5. Date: Fri, 05 Jan 1996 15:06:33 +0100
  6. Organization: Fachbereich Informatik, TH Darmstadt
  7. Message-ID: <30ED3069.15FB7483@intellektik.informatik.th-darmstadt.de>
  8. References: <pcal-0401962039480001@slip-d8.rdrop.com>
  9. NNTP-Posting-Host: kitz.intellektik.informatik.th-darmstadt.de
  10. Mime-Version: 1.0
  11. Content-Type: text/plain; charset=us-ascii
  12. Content-Transfer-Encoding: 7bit
  13. X-Mailer: Mozilla 2.0b4 (X11; I; SunOS 4.1.3 sun4m)
  14.  
  15. Patrick Calahan wrote:
  16. >      I need a little assistance from a C++ guru.
  17. >      I have an abstract class B from which D,E and F are derived
  18. >      I also have an abstract class O from which P, Q and R are derived.
  19. >      Objects derived from O need to perform specific operations given a
  20. >      pair of pointers to B's. The operation to be performed depends on
  21. >      precisely  what kind of B's are given to the O.
  22. >      I thought that by simply overloading member function f in the O's,
  23. >      I could achieve this affect nicely - f(D*,D*), f(D*,E*), f(E*,F*)...
  24. >      could be defined to handle the particualr pair-cases appropriately.
  25. >      A member function in O f(B*,B*) would handle all cases not handled
  26. >      specifically by the subclasses.
  27. >      The only problem is figuring out exactly what type of object a B* is
  28. >      pointing to so that the appropriate call to O.f can be made.  I.e.,
  29. >      given a pointer to a B, I need to cast it to a D*,E*, or F*.
  30. >      On page 640 of Stroustrup, he says that [in dynamic_cast<t>(v)]
  31. >      "If T is void* then v must be a pointer, and the result value is a
  32. >      pointer to the complete object pointed to by v."
  33. >      So, if I read him correctly,
  34. >      dynamic_cast<void*>(p*)
  35. >      should cast p to a pointer to an object of the most complete type of
  36. >      the object pointed to by p, i.e. cast my B* to an D*, E* or F*.
  37. >      This sounds like what I want.
  38. >      Unfortunately, if I try to compile the following using MetroWerks
  39. >      CodeWarrior 7 (I do have RTTI enabled):
  40. >      some_function(B* b1, B*b2, O* o)
  41. >      {
  42. >      // here I need to figure out what types of objects b1 & b2 really are
  43. >      // and cast the pointers so the correct version of f will be called.
  44. >      o->f( dynamic_cast<void*>(b1), dynamic_cast<void*>(b2) );
  45. >      }
  46. >      b1 and b2 apparently get cast to void*; the compiler returns that
  47. >       f(void*,void*) can't be found.
  48. >      What do I need to do here?
  49. >      I'm relatively new to C++, so I might just be looking at the problem
  50. >      incorrectly.
  51. >      I tried to do it just using virtual functions in B, but the fact that
  52. >      I'm dealing with pairs of B's in the O's seems to make this less
  53. >      elegant.
  54. >      Moreover, it makes more sense in my application for O to be a separate
  55. >      class.
  56. >      Many many thanks in advance for any help,
  57.  
  58. Overloaded functions are selected according to the static type of the
  59. arguments. This allows to resolve such calls at compile-time.
  60. Because void-pointers aren't silently converted to any other type the
  61. compiler looks for a function 'O :: f(void*,void*)' which doesn't
  62. exists. 
  63. To use the 'dynamic_cast' you need to narrow the pointers to the desired 
  64. type. For example to narrow a B-pointer to a D-pointer you could write:
  65.  
  66.         void f(B* b) { D* d=dynamic_cast<D*>(b); }
  67.  
  68. If 'b' isn't of type D (or a subclass of D) 'd' will become zero,
  69. otherwise 
  70. 'd' will point to the appropriate D-object. However this solution will
  71. lead
  72. to some code like 'hardcode the possible type and verify the result at
  73. run-time' (ie. sth. similar to a switch-construct). This should clarify
  74. that 
  75. the dynamic-cast will not be very useful to solve your problem.
  76. What you really need is some sort of double-dispatching. You could for
  77. example build up a map where the elements are functor-objects and the
  78. keys
  79. are pairs of typeid's. In this way you can maintain arbitary behavior
  80. connected
  81. to a pair of typeid's. This solution can easily be extended to more then
  82. two
  83. arguments.
  84.  
  85.     Enno
  86.